Date field
canonInput that parses typed dates and opens the calendar panel.
Used in 30 files · 21 areas · 56× — components/accounting, components/callwrapup, components/clen-tymu, components/dialog, components/kpi, components/mail …
Default
export const Default = () => {
const [value, setValue] = useState<string | null>('2026-08-26');
return (
<div style={grid}>
<DateField value={value} onChange={setValue} today={TODAY} ariaLabel="Termín" />
</div>
);
};Variants
same year — 26. 8.
other year — 14. 11. 27
other century — 11. 2. 1988
precision=full — year always shown (data ‚k datu‘) — 31. 5. 2026
futureBias — typed 1. 9. lands on the next occurrence
export const Variants = () => {
const [sameYear, setSameYear] = useState<string | null>('2026-08-26');
const [nextYear, setNextYear] = useState<string | null>('2027-11-14');
const [birth, setBirth] = useState<string | null>('1988-02-11');
const [due, setDue] = useState<string | null>(null);
const [asOf, setAsOf] = useState<string | null>('2026-05-31');
return (
<div style={row}>
<Labeled label="same year — 26. 8.">
<DateField value={sameYear} onChange={setSameYear} today={TODAY} ariaLabel="Uzavření" />
</Labeled>
<Labeled label="other year — 14. 11. 27">
<DateField value={nextYear} onChange={setNextYear} today={TODAY} ariaLabel="Platnost" />
</Labeled>
<Labeled label="other century — 11. 2. 1988">
<DateField value={birth} onChange={setBirth} today={TODAY} ariaLabel="Datum narození" />
</Labeled>
<Labeled label="precision=full — year always shown (data ‚k datu‘) — 31. 5. 2026">
<DateField
value={asOf}
onChange={setAsOf}
precision="full"
max="2026-07-23"
today={TODAY}
ariaLabel="Údaje k datu"
/>
</Labeled>
<Labeled label="futureBias — typed 1. 9. lands on the next occurrence">
<DateField value={due} onChange={setDue} futureBias today={TODAY} ariaLabel="Termín" />
</Labeled>
</div>
);
};States
empty (placeholder)
filled
error
disabled
→ čtvrtek 30. 7.
Nerozumím datu
export const States = () => {
const [empty, setEmpty] = useState<string | null>(null);
const [filled, setFilled] = useState<string | null>('2026-08-26');
const [error, setError] = useState<string | null>('2026-08-26');
const [disabled, setDisabled] = useState<string | null>('2026-08-26');
return (
<div style={grid}>
<div style={row}>
<Labeled label="empty (placeholder)">
<DateField value={empty} onChange={setEmpty} today={TODAY} ariaLabel="Termín" />
</Labeled>
<Labeled label="filled">
<DateField value={filled} onChange={setFilled} today={TODAY} ariaLabel="Termín" />
</Labeled>
<Labeled label="error">
<DateField value={error} onChange={setError} error today={TODAY} ariaLabel="Termín" />
</Labeled>
<Labeled label="disabled">
<DateField
value={disabled}
onChange={setDisabled}
disabled
today={TODAY}
ariaLabel="Termín"
/>
</Labeled>
</div>
<div style={row}>
{/* Typing echo — `.dp-echo` markup as DateField renders it while the user types;
rendered statically here because the echo exists only during typing. */}
<Labeled label="typing echo (static .dp-echo)">
<div className="dp-fieldset">
<div className="dp-field">
<input className="dp-input" defaultValue="+7" aria-label="Termín" readOnly />
<button type="button" className="dp-open" aria-label="Otevřít kalendář">
<Icon name="calendar" />
</button>
</div>
<div className="dp-echo">→ čtvrtek 30. 7.</div>
</div>
</Labeled>
<Labeled label="typing echo — invalid (static .dp-echo.bad)">
<div className="dp-fieldset">
<div className="dp-field err">
<input className="dp-input" defaultValue="32.13." aria-label="Termín" readOnly />
<button type="button" className="dp-open" aria-label="Otevřít kalendář">
<Icon name="calendar" />
</button>
</div>
<div className="dp-echo bad">Nerozumím datu</div>
</div>
</Labeled>
</div>
<span style={{ color: 'var(--fg-muted)', font: 'var(--small)' }}>
Focus: `.dp-field:focus-within` draws the accent border + 3px accent ring; the calendar
opens from the icon or ↓, never from focus alone.
</span>
</div>
);
};Composition
Zadejte datum
export const Composition = () => {
const [due, setDue] = useState<string | null>('2026-08-26');
const [start, setStart] = useState<string | null>(null);
return (
<div style={grid}>
<Labeled label="form field — label from <Field>, single date">
<Field label="Termín">
<DateField value={due} onChange={setDue} futureBias today={TODAY} ariaLabel="Termín" />
</Field>
</Labeled>
<Labeled label="form field with error — message from <Field>, ring from the field">
<Field label="Začátek" error="Zadejte datum">
<DateField
value={start}
onChange={setStart}
error
futureBias
today={TODAY}
ariaLabel="Začátek"
/>
</Field>
</Labeled>
<Labeled label="dialog footer follows the field">
<div style={{ display: 'grid', gap: 'var(--sp-4)', minWidth: 360 }}>
<Field label="Termín">
<DateField value={due} onChange={setDue} futureBias today={TODAY} ariaLabel="Termín" />
</Field>
<div
style={{
display: 'flex',
gap: 'var(--sp-3)',
justifyContent: 'flex-end',
paddingTop: 'var(--sp-4)',
borderTop: '1px solid var(--border)',
}}
>
<Button kbd="Esc">Cancel</Button>
<Button variant="primary" kbd="⌘↵">
Save
</Button>
</div>
</div>
</Labeled>
</div>
);
};